package com.qf.shiro;

import com.qf.pojo.DtsAd;
import com.qf.pojo.DtsAdmin;
import com.qf.service.AdminService;
import com.qf.service.PermissionService;
import com.qf.service.RoleService;
import com.qf.util.bcrypt.BCryptPasswordEncoder;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.aspectj.weaver.bcel.BcelAccessForInlineMunger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
//自定义Realm, shiro中用来对用户名密码进行校验和登录后授权
public class AdminAuthorizingRealm extends AuthorizingRealm {
    @Autowired
    private AdminService adminService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permService;


    //用户登录成功后, 对用户进行授权, 授予对应的角色和权限
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {

        //1. 获取认证后的当前用户对象, 这里将参数强转成我们自己封装的用户实体类对象
        DtsAdmin admin = (DtsAdmin) getAvailablePrincipal(principal);

        //2. 根据用户对象获取角色ids
        Integer[] roleIds = admin.getRoleIds();

        //3. 根据角色id集合到数据库中查找对应的角色名称集合
        Set<String> roleSet = roleService.queryByIds(roleIds);

        //4. 根据角色id集合, 到数据库中查询对应的权限字符串集合
        Set<String> permSet = permService.queryPermissonByRoleIds(roleIds);

        //5. 将角色名称集合, 和权限字符串集合交给shiro框架
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roleSet);
        info.setStringPermissions(permSet);

        //6. 返回封装后的shiro权限对象
        return info;
    }








    //接收页面传入的用户名密码, 根据数据库的用户名密码进行校验





    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        //1. 获取用户页面中输入的用户名, 密码
        UsernamePasswordToken UserNameAndPwd = (UsernamePasswordToken) token;
        String username = UserNameAndPwd.getUsername();
        String password = new String(UserNameAndPwd.getPassword());

        //2. 判断如果用户名为空, 返回异常提示信息
        if (StringUtils.isEmpty(username)) {
            throw new AccountException("用户名为空!");
        }

        //3. 判断如果密码为空, 返回异常提示信息
        if (StringUtils.isEmpty(password)) {
            throw new AccountException("密码为空!");
        }

        //4. 根据用户名, 获取用户对象集合
        List<DtsAdmin> userList = adminService.findAdminByUserName(username);

        //5. 判断如果获取不到用户对象, 返回异常提示信息
        if (userList == null || userList.size() == 0){
            throw new UnknownAccountException("用户名错误!");
        }

        //6. 如果用户对象大于1个, 那么说明存在同名账户, 不允许登录
        if (userList.size() >= 2) {
            throw new UnknownAccountException("存在同名账户, 请联系管理员!");
        }

        DtsAdmin admin = userList.get(0);

        //7. 判断如果密码不正确返回异常提示信息
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        //BCrypt工具类进行校验, 密码使用的BCrypt算法进行的加密
        //第一个参数是明文密码, 第二个参数是加密后的密码, 返回校验结果
        if (!encoder.matches(password, admin.getPassword())) {
            throw new UnknownAccountException("密码错误!");
        }

        //8. 封装shiro指定的对象交给shiro框架处理
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(admin, password, this.getName());

        return info;
    }


}
